package fileController

import (
	"CMETO/utils"
	"fmt"
	"net/http"
	"os"
	"sort"
	"strconv"

	"github.com/gin-gonic/gin"
)

type SliceFileUpload struct {
}

// 检查文件状态
func (s SliceFileUpload) CheckStatus(ctx *gin.Context) {
	// 获取hash值
	hash := ctx.Query("hash")
	// 获取切片长度
	length, _ := strconv.Atoi(ctx.Query("length"))
	hashPath := fmt.Sprint("./static/upload/", hash)
	// 判断哈希文件在不在
	fileExist := utils.OsTools{}.CheckFile(hashPath + ".txt")
	if fileExist {
		ctx.JSON(http.StatusOK, gin.H{
			"msg":  "已存在",
			"type": 5,
		})
		return
	}

	isExist := utils.OsTools{}.CheckPath(hashPath)
	chunkList := []string{}
	if isExist {
		// 文件夹存在，读取文件，判断长度
		files, err := os.ReadDir(hashPath)
		if err != nil {
			s.DataNo(ctx)
			return
		}
		for _, f := range files {
			fileName := f.Name()
			chunkList = append(chunkList, fileName)
		}
		// 长度够了，不用再上传了
		if len(chunkList) == length {
			ctx.JSON(http.StatusOK, gin.H{
				"msg":  "已完成",
				"type": 2,
			})
			return
		}
		// 长度不够，返回文件序列数组
		s.CanContinue(ctx, chunkList)
	} else {
		// 文件夹不存在，创建文件夹
		if err := os.Mkdir(hashPath, 0777); err != nil {
			s.DataNo(ctx)
		} else {
			ctx.JSON(http.StatusOK, gin.H{
				"msg":  "初始化",
				"type": 4,
			})
		}
	}
}

// 文件分片传输
func (s SliceFileUpload) UploadSingleSlice(ctx *gin.Context) {
	// 获取hash
	fileHash := ctx.PostForm("hash")
	// 获取文件
	file, err := ctx.FormFile("file")
	// 获取文件序列
	index := ctx.Param("index")
	if err != nil {
		s.DataNo(ctx)
		return
	}
	hashPath := fmt.Sprint("./static/upload/", fileHash)
	isExist := utils.OsTools{}.CheckPath(hashPath)
	if !isExist {
		s.DataNo(ctx)
		return
	}
	chunkList := []string{}
	if err1 := ctx.SaveUploadedFile(file, fmt.Sprint(hashPath, "/", index)); err1 != nil {
		s.DataNo(ctx)
	} else {
		// 文件夹存在，读取文件，判断长度
		files, err := os.ReadDir(hashPath)
		if err != nil {
			s.DataNo(ctx)
			return
		}
		for _, f := range files {
			fileName := f.Name()
			chunkList = append(chunkList, fileName)
		}
		s.CanContinue(ctx, chunkList)
	}
}

// 合并分片
func (s SliceFileUpload) MergeChunks(ctx *gin.Context) {
	// 获取hash
	hash := ctx.Query("hash")
	// 获取文件名
	fileName := ctx.Query("fileName")
	// 拼接路径
	hashPath := fmt.Sprint("./static/upload/", hash)
	// 判断文件夹是否存在
	isExist := utils.OsTools{}.CheckPath(hashPath + "/" + fileName)
	if isExist {
		ctx.JSON(http.StatusOK, gin.H{
			"msg": "ok",
			"url": fileName,
		})
		return
	}
	// 创建文件
	finalFile, err := os.Create("./static/upload/" + fileName)
	// 创建hash文件
	os.Create("./static/upload/" + hash + ".txt")
	if err != nil {
		s.DataNo(ctx)
		return
	}
	defer finalFile.Close()

	// 读取文件块
	files, err2 := os.ReadDir(hashPath)
	if err2 != nil {
		s.DataNo(ctx)
		return
	}
	// 排序
	sort.Slice(files, func(i, j int) bool {
		a, _ := strconv.Atoi(files[i].Name())
		b, _ := strconv.Atoi(files[j].Name())
		return a < b
	})
	// 写入最终文件
	for _, f := range files {
		fileBuffer, err3 := os.ReadFile(hashPath + "/" + f.Name())
		if err3 != nil {
			s.DataNo(ctx)
			return
		}
		finalFile.Write(fileBuffer)
	}
	// 返回地址
	ctx.JSON(http.StatusOK, gin.H{
		"mag": "ok",
		"url": fileName,
	})
	// 合并之后删掉分片文件夹
	os.RemoveAll(hashPath)
}

// 七牛云分片尝试
func (s SliceFileUpload) SliceUploadToQiniu(ctx *gin.Context) {

}

func (s SliceFileUpload) DataNo(ctx *gin.Context) {
	ctx.JSON(http.StatusOK, gin.H{
		"msg":  "异常",
		"type": 1,
	})
}
func (s SliceFileUpload) CanContinue(ctx *gin.Context, chunkList []string) {
	ctx.JSON(http.StatusOK, gin.H{
		"msg":       "可继续",
		"type":      2,
		"chuckList": chunkList,
	})
}
